package com.iceland.server.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;

import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class Server {


    protected ServerBootstrap sb;
    protected EventLoopGroup bossGroup;
    protected EventLoopGroup workerGroup;
    protected InetSocketAddress inetSocketAddress;

    int port;


    private volatile AtomicBoolean closing=new AtomicBoolean(false);

    public Server(int bossThreadCount, int workThreadCount, Class channelClass){
        bossGroup=new NioEventLoopGroup(bossThreadCount);
        workerGroup=new NioEventLoopGroup(workThreadCount);
        sb=new ServerBootstrap();
        sb.group(bossGroup, workerGroup).channel(channelClass);
        preStart(sb);
    }

    protected abstract void preStart(ServerBootstrap sb);
    protected abstract void afterStart();

    /**
     * 0表示分配随机空闲端口
     * @param port
     * @throws InterruptedException
     * @return 绑定的端口号
     */
    public int startServer(int port) throws InterruptedException {
        inetSocketAddress = new InetSocketAddress(port);
        ChannelFuture bind =sb.bind(inetSocketAddress).sync();
        afterStart();
        this.port=((InetSocketAddress)bind.channel().localAddress()).getPort();
        return this.port;
    }
//    /**
//     * 异步启动服务，0表示分配随机空闲端口
//     * @param port
//     * @throws InterruptedException
//     * @return 绑定的端口号
//     */
//    public int startServerAsync(int port) {
//        InetSocketAddress inetSocketAddress = new InetSocketAddress(port);
//        ChannelFuture bind = sb.bind(inetSocketAddress);
//        this.port=((InetSocketAddress)bind.channel().localAddress()).getPort();
//        return this.port;
//    }

    public int getPort() {
        return port;
    }

    public void close(){
        closing.set(true);
        if(workerGroup!=null){
            workerGroup.shutdownGracefully();
        }
        if(bossGroup!=null){
            bossGroup.shutdownGracefully();
        }
    }

    public boolean isClosing(){
        return closing.get();
    }

}
